pub struct Post{
    state: Option<Box<dyn State>>,
    content: String,
}

impl Post {
    pub fn new()->Post{
        Post{
            state: Some(Box::new(Draft{})),
            content: String::new()
        }
    }

    pub fn add_text(&mut self, txt: &str){
        self.content.push_str(txt);
    }

    pub fn content(&self)->&str{
        self.state.as_ref().unwrap().content(&self)
    }

    pub fn request_review(&mut self){
        if let Some(s)=self.state.take(){
            self.state = Some(s.request_review())
        }
    }

    pub fn approve(&mut self){
        if let Some(s)=self.state.take(){
            self.state = Some(s.approve())
        }
    }

}

trait State{
    fn request_review(self: Box<Self>)->Box<dyn State>;
    fn approve(self: Box<Self>)->Box<dyn State>;
    fn content<'x>(&self, post: &'x Post)->&'x str{
        ""
    }
}

struct Draft{}

impl State for Draft {
    fn request_review(self: Box<Self>) -> Box<dyn State> {
        Box::new(PendingReview{})
    }

    fn approve(self: Box<Self>) -> Box<dyn State> {
        self
    }
}

struct PendingReview{}

impl State for PendingReview {
    fn request_review(self: Box<Self>) -> Box<dyn State> {
        self
    }

    fn approve(self: Box<Self>) -> Box<dyn State> {
        Box::new(Published{})
    }
}

struct Published{}

impl State for Published {
    fn request_review(self: Box<Self>) -> Box<dyn State> {
        self
    }

    fn approve(self: Box<Self>) -> Box<dyn State> {
        self
    }

    fn content<'x>(&self, post: &'x Post) -> &'x str {
        &post.content
    }
}



// pub struct AveragedCollection{
//     pub list: Vec<i32>,
//     pub average: f64,
// }
//
// impl AveragedCollection {
//     pub fn add(&mut self, value:i32){
//         self.list.push(value);
//         self.update_average();
//     }
//
//     pub fn remove(&mut self){
//         let result = self.list.pop();
//         match result {
//             Some(val)=>{
//                 self.update_average();
//                 Some(val);
//             },
//             None=>None,
//         }
//     }
//
//     pub fn average(&self)->f64{
//         self.average
//     }
//
//     fn update_average(&mut self){
//         let total:i32 = self.list.iter().sum();
//         self.average = total as f64 / self.list.len() as f64;
//     }
//
// }